﻿using SalesPages.DomainModel.DomainModel;
using SalesPages.DomainModel.SearchCriteria;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using EntityFramework.Extensions;
using SalesPagesDemo.Common;
using SalesPages.Infrastructure;
using SalesPages.DomainModel.ViewModel;

namespace SalesPages.EntityFrameworkRepository.Repository
{
    public abstract class BaseRepertory<TEntity, Key> : IBsaeRepertory<TEntity> where TEntity : BaseEntity<Key>, new()
    {
        public DbContext Context
        {
            get
            {
                return EFUnitOfWork.Current.Value.Context;
            }
        }

        public DbSet<TEntity> Entities
        {
            get { return Context.Set<TEntity>(); }
        }

        public void Create(TEntity entity)
        {
            Entities.Add(entity);
        }

        public List<TEntity> GetAll()
        {
            return Entities.ToList();
        }

        public void Insert(TEntity entity)
        {
            Entities.Add(entity);
        }

        public void Insert(IEnumerable<TEntity> entities)
        {
            Entities.AddRange(entities);
        }

        public void Update(TEntity entity)
        {
            Context.Entry(entity).State = EntityState.Modified;
        }
            
        public virtual void Delete(TEntity entity)
        {
            Entities.Remove(entity);
        }

        public virtual void Delete(IEnumerable<TEntity> entities)
        {
            Entities.RemoveRange(entities);
        }

        public virtual void Delete(Expression<Func<TEntity, bool>> filterExpression)
        {
            Entities.Where(filterExpression).Delete();
        }

        public void DeleteByKey(Key Id)
        {
            Entities.Where(e => e.Id.Equals(Id)).Delete();
        }

        public TEntity FindByKey(object key)
        {
            return Entities.Find(key);
        }

        public IEnumerable<TEntity> Search(Expression<Func<TEntity, bool>> filterExpression)
        {
            return Entities.Where(filterExpression);
        }

        public IPagedList<TEntity> Search(Expression<Func<TEntity, bool>> filterExpression, PageCondition pageCondition)
        {
            var query = pageCondition.NeedNoTracking ? Entities.AsNoTracking() : Entities;
            return query.Where(filterExpression).ToPageList(pageCondition);
        } 
    }

    public static class RepertoryUtils
    {
        public static IPagedList<TEntity> ToPageList<TEntity>(this IQueryable<TEntity> query, PageCondition pageCondition) where TEntity : class
        {
            query = query.OrderBy(pageCondition.SortFileds, pageCondition.OrderAsc);

            var totalCount = 0;
            try
            {
                totalCount = query.FutureCount();
            }
            catch
            {
                totalCount = query.Count();
            }

            return new PagedList<TEntity>(query, pageCondition.PageSize, pageCondition.PageIndex);
        }
     
    }
}
